﻿using System;
using System.Reflection;
using System.Xml.Linq;
using Phoenix.Xna.Framework.Xml;

namespace Phoenix.Xna.Framework.Serialization.Markup.Fields
{
    /// <summary>
    /// The markup information for a value field.
    /// </summary>
    internal class ValueMarkupField : MarkupFieldBase<object>
    {
        #region IMarkupElement Members

        /// <summary>
        /// Serialize the element to XML.
        /// </summary>
        /// <returns>The element markup serialzed as an XElement.</returns>
        public override XElement Serialize()
        {
            XElement element = new XElement(NamespaceCache.GetNamespaceFor(ObjectType) + ObjectType.Name.Replace("-", "`"), _value);
            element.SetAttribute(AttributeIDs.FieldIDAttribute, Name);
            element.SetAttribute(AttributeIDs.IsFieldAttribute, true);
            return element;
        }

        /// <summary>
        /// Deserialize the element from an XElement.
        /// </summary>
        /// <param name="xml">The XElement to deserialize this element from.</param>
        public override void Deserialize(XElement element)
        {
            ObjectType = NamespaceCache.GetType(element.Name.LocalName.Replace("`", "-"), element.Name.Namespace);

            if (element != null)
            {
                Name = element.ReadAttribute<string>(AttributeIDs.FieldIDAttribute);
                _value = element.Value;
            }
        }

        #endregion

        #region IMarkupField Members

        /// <summary>
        /// Extract the markup information from the FieldInfo for this field.
        /// </summary>
        /// <param name="field">The FieldInfo for this field.</param>
        /// <param name="value">The value of the field.</param>
        public override void ExtractMarkup(FieldInfo field, object value)
        {
            ObjectType = field.FieldType;
            Name = field.Name;
            ShouldPersist = SerializableFieldAttribute.ShouldPersist(field, value);

            if (ShouldPersist)
            {
                _value = value;
            }
        }

        /// <summary>
        /// Sets the value of MarkupField to the instance's field value.
        /// </summary>
        /// <param name="instance">The instance to set the field on.</param>
        public override void SetValue(object instance)
        {
            FieldInfo field = instance.GetType().GetField(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            field.SetValue(instance, _value.TypeConvertionCast(field.FieldType));
        }

        #endregion
    }
}